﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Security.Cryptography;
using System.IO;
using System.Text;

/// <summary>
/// Summary description for RSA
/// </summary>

public class RSACrypto
{
   private RSACryptoServiceProvider _sp;

   const int keySize = 1024;

   public RSAParameters ExportParameters(bool includePrivateParameters)
   {
      return _sp.ExportParameters(includePrivateParameters);
   }

   public void GenerateKeys(string PrivateKeyFile, string PublicKeyFile)
   {
      RSACryptoServiceProvider sp = new RSACryptoServiceProvider(keySize);

      string str = sp.ToXmlString(true);
      TextWriter writer = new StreamWriter(PrivateKeyFile);
      writer.Write(str);
      writer.Close();

      str = sp.ToXmlString(false);
      writer = new StreamWriter(PublicKeyFile);
      writer.Write(str);
      writer.Close();
   }

   public void InitCrypto(string keyFileName)
   {
      const int PROVIDER_RSA_FULL = 1;
      const string CONTAINER_NAME = "SpiderContainer";
      CspParameters cspParams;
      cspParams = new CspParameters(PROVIDER_RSA_FULL);
      cspParams.KeyContainerName = CONTAINER_NAME;
      cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
      cspParams.ProviderName = "Microsoft Strong Cryptographic Provider"; 
      // To avoid repeated costly key pair generation
      _sp = new RSACryptoServiceProvider(cspParams);
      string path = keyFileName;
      System.IO.StreamReader reader = new StreamReader(path);
      string data = reader.ReadToEnd();
      _sp.FromXmlString(data);
   }

   public byte[] Encrypt(string txt)
   {
      byte[] result;

      ASCIIEncoding enc = new ASCIIEncoding();
      int numOfChars = enc.GetByteCount(txt);
      byte[] tempArray = enc.GetBytes(txt);
      result = _sp.Encrypt(tempArray, false);

      return result;
   }

   public byte[] Decrypt(byte[] txt)
   {
      byte[] result;

      result = _sp.Decrypt(txt, false);

      return result;
   }

   public string DecryptToText(string txt)
   {
      return StringHelper.ASCIIBytesToString(StringHelper.FromBase64(StringHelper.ASCIIBytesToString(Decrypt(StringHelper.HexStringToBytes(txt)))));
   }

   public static string DecryptValue(string txt)
   {
      RSACrypto rsac = new RSACrypto();
      rsac.InitCrypto(System.Configuration.ConfigurationSettings.AppSettings["rsaPrivateKeyFilePath"]);

      return rsac.DecryptToText(txt);
   }
}

public class StringHelper
{
   public static byte[] HexStringToBytes(string hex)
   {
      if (hex.Length == 0)
      {
         return new byte[] { 0 };
      }

      if (hex.Length % 2 == 1)
      {
         hex = "0" + hex;
      }

      byte[] result = new byte[hex.Length / 2];

      for (int i = 0; i < hex.Length / 2; i++)
      {
         result[i] = byte.Parse(hex.Substring(2 * i, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
      }

      return result;
   }

   public static string BytesToHexString(byte[] input)
   {
      StringBuilder hexString = new StringBuilder(64);

      for (int i = 0; i < input.Length; i++)
      {
         hexString.Append(String.Format("{0:X2}", input[i]));
      }
      return hexString.ToString();
   }

   public static string BytesToDecString(byte[] input)
   {
      StringBuilder decString = new StringBuilder(64);

      for (int i = 0; i < input.Length; i++)
      {
         decString.Append(String.Format(i == 0 ? "{0:D3}" : "-{0:D3}", input[i]));
      }
      return decString.ToString();
   }

   // Bytes are string
   public static string ASCIIBytesToString(byte[] input)
   {
      System.Text.ASCIIEncoding enc = new ASCIIEncoding();
      return enc.GetString(input);
   }
   public static string UTF16BytesToString(byte[] input)
   {
      System.Text.UnicodeEncoding enc = new UnicodeEncoding();
      return enc.GetString(input);
   }
   public static string UTF8BytesToString(byte[] input)
   {
      System.Text.UTF8Encoding enc = new UTF8Encoding();
      return enc.GetString(input);
   }

   // Base64
   public static string ToBase64(byte[] input)
   {
      return Convert.ToBase64String(input);
   }

   public static byte[] FromBase64(string base64)
   {
      return Convert.FromBase64String(base64);
   }
}